/**
    Copyright (C) 2011  Alexander Vollmer

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.jefb.service.impl;

import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.jefb.annotations.LazyInit;
import org.jefb.dao.ICommonDao;
import org.jefb.entity.CommonSearchCriteria;
import org.jefb.entity.IBasicEntity;
import org.jefb.service.ICommonPersistenceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class CommonPersistenceService implements ICommonPersistenceService, Serializable {

	private static final long serialVersionUID = 7114513243013892070L;
	
	@Autowired
	private ICommonDao commonDAO;
	
//	@SuppressWarnings({ "unchecked", "rawtypes" })
//	@Transactional(propagation = Propagation.REQUIRED)
//	public <T,CC> Collection<CC> getLazyCollection(T entity, Class<CC> collectionClazz, String marker) {
//		Class<? extends Object> clazz = entity.getClass();
//		Method[] methods = clazz.getMethods();
//		for(Method method:methods){
//			Annotation[] annotations = method.getAnnotations();
//			for(Annotation annotation:annotations){
//				if (annotation instanceof LazyInit) {
//					LazyInit lazyInitAnnotation = (LazyInit) annotation;
//					if(lazyInitAnnotation.value().equals(marker)){
//						try {
//							Collection<CC> lazyCollection = (Collection<CC>)method.invoke(entity, new Object[]{});
//							if(lazyCollection!=null && !lazyCollection.isEmpty()){
//								return Collections.unmodifiableCollection(lazyCollection);
//							}
//							return Collections.EMPTY_LIST;
//						} catch (Exception e) {
//							e.printStackTrace();
//						}
//					}
//				}
//			}
//		}
//		return Collections.EMPTY_LIST;
//	}
	
	@Transactional(readOnly=true)
	public <T> List<T> findAll(Class<T> clazz) {
		try{
			return commonDAO.findAll(clazz);
		}catch (RuntimeException re){
			//TODO handle it
			return null;
		}
	}
	
	@Transactional(readOnly=true)
	public <T> List<T> findAllByExample(T entity) {
		try{
			return commonDAO.findByExample(entity);
		}catch (RuntimeException re){
			//TODO handle it
			return null;
		}
	}
	

	@Transactional(readOnly=true)
	public <T> List<T> findByCriteria(T entity, CommonSearchCriteria commonSearchCriteria) {
		return commonDAO.findByCriteria(entity,commonSearchCriteria);
	}
	
	@Transactional(readOnly=false, propagation = Propagation.REQUIRED)
	public <T> void persistEntity(T entity){
		if(entity!=null){
			commonDAO.persist(entity);
		}else{
			//log and throw exception
		}
	}
	
	@Transactional(readOnly=false,propagation = Propagation.REQUIRED)
	public <T extends IBasicEntity> void deleteEntity(T entity) {
		commonDAO.getSession().refresh(entity);
		this.commonDAO.remove(entity.getClass(), entity.getId());
	}
	
	@Transactional(readOnly=false,propagation = Propagation.REQUIRED)
	public <T> void updateEntity(T entity) {
		commonDAO.merge(entity);
	}
	
	@Transactional(readOnly=true)
	public <T> Long getTotalSizeByCriteria(T searchCriteria) {
		return commonDAO.getTotalSizeByCriteria(searchCriteria);
	}

	public void setCommonDAO(ICommonDao commonDAO) {
		this.commonDAO = commonDAO;
	}

	public ICommonDao getCommonDAO() {
		return commonDAO;
	}

	public <T> void refresh(T entity) {
		commonDAO.refresh(entity);		
	}

	public void flush() {
		commonDAO.flush();	
	}

	public <T> List<T> findByExample(T example, String... excudes) {
		return commonDAO.findByExample(example, excudes);
	}
}
